import { createEffect, createSignal, onCleanup, onMount, Show } from "solid-js";
import { useSearchParams } from "@solidjs/router"
import { ProjectService } from '@/service/projects-api';
import { ComUtils } from '@/utils/Com';
import { MessageBox } from '@/utils/messagebox';
import { setTitle } from "@/store/tabs";
import '@/assets/css/editor.css'
import { DogEditor } from "@/utils/dog-editor";
import { BrowserUtils } from "@/us/browser";

enum EditorType {
    Blockly,
    Text
}

const refreshtIcon = ComUtils.getResourceUrl('/icons/refresh.svg')
const importIcon = ComUtils.getResourceUrl('/icons/import.svg')
const blocklyIcon = ComUtils.getResourceUrl('/icons/blockly_36.png')
const textIcon = ComUtils.getResourceUrl('/icons/obj.svg')
const saveIcon = ComUtils.getResourceUrl('/icons/save.svg')
const saveAsIcon = ComUtils.getResourceUrl('/icons/save-as.svg')
const runIcon = ComUtils.getResourceUrl('/icons/run.svg')
const loadingIcon = ComUtils.getResourceUrl('/icons/loading-g.svg')

export default function () {
    let iframe: any
    const [query] = useSearchParams()
    const [source, setSource] = createSignal<ProjectItem>()
    const [editorType, setEditorType] = createSignal<EditorType>(EditorType.Blockly)
    const [loading, setLoading] = createSignal(false)

    const changeEditor = async (t: EditorType) => {
        if (editorType() === t) {
            return
        }
        setEditorType(t)

        iframe.contentWindow.postMessage({ type: 'change-editor', data: t }, '*')
    }

    const loadSource = async () => {
        const res = await ProjectService.one(query.id as any).catch(() => undefined)
        setSource(res)
        if (source()?.type === 'editorPlugin') {
            setEditorType(EditorType.Text)
        }
        getProject()
    }

    const importCode = async () => {
        try {
            const res = await BrowserUtils.openFile<string>()
            const data = source()
            if (!data || !res) {
                return
            }
            data.source = res
            setSource(data)
            getProject()
        } catch (error) {
            MessageBox.error(ComUtils.tr('load_fail'))
            console.log(error)
        }
    }

    const saveAsCode = () => {
        let item = source()
        if (!item) {
            return
        }
        if (item.programmingType === 'blockly' || (!item.programmingType && item.code.length === 0)) {
            const data = item.source;

            BrowserUtils.downloadWithData(data, `${item.id}.json`, 'application/json')

        } else {
            const data = item.code
            BrowserUtils.downloadWithData(data, `${item.id}.js`, 'application/javascript')
        }
    }

    const saveCode = async () => {
        iframe.contentWindow.postMessage({ type: 'save-project', data: '' }, '*')
    }

    const refreshProject = () => {
        let item = source()
        if (!item) {
            return
        }
        if(!item.enabled){
            MessageBox.warning(ComUtils.tr('project_disabled'));
            return
        }
        setLoading(true)
        const id = item.id
        ComUtils.callChromeMethod('updateScript', { id }).then(() => {
            MessageBox.success(ComUtils.tr('refresh_success'))
        }).catch(() => {
            MessageBox.error(ComUtils.tr('refresh_fail'))
        }).finally(() => {
            setLoading(false)
        })
    }

    const runScript = () => {
        iframe.contentWindow.postMessage({ type: 'run-project', data: '' }, '*')
    }

    const runAndSave = (item: ProjectItem) => {

        if (item.type === 'content') {
            return;
        }
        saveCode().then(() => {
            return ComUtils.callChromeMethod('runScript', { id: item.id, sw: screen.width, sh: screen.height })
        }).then(() => {
            if (item.type === 'sidePanel') {
                ComUtils.callChromeMethod('openSidePanel', undefined)
            }
            MessageBox.success(ComUtils.tr('run_success'))
        }).catch((err) => {
            console.log(err)
            MessageBox.error(ComUtils.tr('run_fail'))
        })
    }

    const getProject = async () => {
        const data = source()
        if (!data) {
            return
        }
        const plugins = await ProjectService.plugins(data.id)
        const codes = plugins.map(p => p.code)
        iframe.contentWindow.postMessage({
            type: 'set-project', data: {
                projoct: data,
                plugins: codes
            }
        }, '*')
    }

    const updateProject = (proj: ProjectItem) => {
        const data = source()
        if (!data) {
            return
        }
        data.code = proj.code
        data.source = proj.source
        data.updateTime = proj.updateTime
        setSource(data)

        ProjectService.save(data).then(() => {
            MessageBox.success(ComUtils.tr('save_success'))
        }).catch(() => {
            MessageBox.error(ComUtils.tr('save_fail'))
        })
    }

    const editorMessageHandler = (e: any) => {
        if (!e.data?.type) {
            return
        }
        switch (e.data.type) {
            case 'update-project':
                updateProject(e.data.data)
                break
            case 'run-project':
                runAndSave(e.data.data)
                break
            case 'get-project':
                getProject()
                break
            case 'call-func':
                callFunc(e.data.data)
        }
    }

    const callFunc = (data: any) => {
        const res = DogEditor.callFunc(data.funcName, ...data.args)
        iframe.contentWindow.postMessage({ type: 'call-func-result', data: res }, '*')
    }

    const initEvent = () => {

        if (!iframe?.contentWindow) {
            return
        }
        window.addEventListener('message', editorMessageHandler)
    }

    const clearEditor = () => {
        window.removeEventListener('message', editorMessageHandler)
        iframe.contentWindow.postMessage({ type: 'clear-editor', data: '' }, '*')
    }

    createEffect(() => {
        setTitle(source()?.name || 'untitled')
    })

    onMount(async () => {
        initEvent()
        loadSource()
    })

    onCleanup(() => {
        setTitle('')
        clearEditor()
    })

    const loadingBlock = <div class=" fixed left-0 top-0 z-[9999] backdrop:blur bg-[rgba(0,0,0,0.4)] w-full h-full flex items-center justify-center" style={{ 'display': loading() ? 'flex' : 'none' }}>
        <img class="w-16 h-16" src={loadingIcon} alt="loading" />
    </div>
    return <div class='w-full h-full relative overflow-hidden'>
        {loadingBlock}
        <div class="toolbar absolute z-[999] top-0 right-0 flex items-center justify-end gap-2 p-2">
            <Show when={source() && source()?.type && source()?.type === 'content'}>
                <button title={ComUtils.tr('refresh')} onclick={refreshProject}>
                    <img class='w-6 h-6' src={refreshtIcon} alt="refreshtIcon" />
                </button>
            </Show>
            <Show when={source() && source()?.type && (source()?.type === 'sidePanel' || source()?.type === 'window')}>
                <button title={ComUtils.tr('run')} onclick={() => runScript()}>
                    <img class="w-5 h-5" src={runIcon} alt="run" />
                </button>
            </Show>
            <Show when={source()?.programmingType !== 'text' && source()?.external !== true}>
                <button title={ComUtils.tr('import')} onclick={importCode}>
                    <img class='w-6 h-6' src={importIcon} alt="importIcon" />
                </button>
            </Show>
            <Show when={source()?.programmingType === 'both'}>
                <button title={ComUtils.tr('blockly')} onclick={() => changeEditor(EditorType.Blockly)}>
                    <img class='w-6 h-6' src={blocklyIcon} alt="blocklyIcon" classList={{ 'opacity-40': editorType() === EditorType.Blockly }} />
                </button>
            </Show>
            <Show when={source()?.programmingType === 'both'}>
                <button title={ComUtils.tr('text_code')} onclick={() => changeEditor(EditorType.Text)} classList={{ 'opacity-40': editorType() === EditorType.Text }}>
                    <img class='w-6 h-6' src={textIcon} alt="textIcon" />
                </button>
            </Show>

            <button title={ComUtils.tr('save')} onclick={saveCode}>
                <img class='w-6 h-6' src={saveIcon} alt="saveIcon" />
            </button>
            <button title={ComUtils.tr('save_as')} onclick={saveAsCode}>
                <img class='w-6 h-6' src={saveAsIcon} alt="saveAsIcon" />
            </button>

        </div>
        <iframe ref={iframe} class='h-full w-full' src="/editor-sandbox.html"></iframe>
    </div>
}